<?php

namespace App\Libs\Wechat;

use GuzzleHttp\Client;
use Cache;
use Log;

// Todo 临时
class WechatService
{
    protected $client;
    protected $appId;
    protected $appSecret;
    protected $accessToken;

    public function __construct($appId, $appSecret)
    {
        $this->appId     = $appId;
        $this->appSecret = $appSecret;
        $this->client    = new Client();
//        info('args', func_get_args());
        $this->getAccessToken();
    }

    public function forceRefreshToken()
    {
        $accessToken = $this->refreshToken();

        if (empty($accessToken))
            for ($i = 0; $i < 3; $i++) {
                sleep($i * $i * $i);
                $accessToken = $this->refreshToken();
                if (!empty($accessToken)) {
                    break;
                }
            }
        Cache::put('WX_ACCESS_TOKEN_' . $this->appId, $accessToken, 110);
    }

    /**
     * 获取微信code
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     */
    public function getCode()
    {
        $state    = date('His');
        $callback = urlencode(route('wechat.oauth'));
        $uri      = "https://open.weixin.qq.com/connect/oauth2/authorize?" .
            "appid={$this->appId}&redirect_uri={$callback}" .
            "&response_type=code&scope=snsapi_base&state={$state}#wechat_redirect";

        Log::info("获取微信用户code: {$uri}");

        return redirect($uri);
    }

    public function getRedirectUri()
    {
        $state    = date('His');
        $callback = urlencode(route('wechat.oauth'));
        $uri      = "https://open.weixin.qq.com/connect/oauth2/authorize?" .
            "appid={$this->appId}&redirect_uri={$callback}" .
            "&response_type=code&scope=snsapi_base&state={$state}#wechat_redirect";

        Log::info("获取微信用户code: {$uri}");

        return $uri;
    }

    /**
     * 获取用户openid信息
     * @param $code
     * @return mixed
     */
    public function getOAuth($code)
    {
        $uri = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->appId}&" .
            "secret={$this->appSecret}&code={$code}&grant_type=authorization_code";

        $response = $this->client->request('GET', $uri);
        $content  = $response->getBody()->getContents();
        Log::info("获取微信用户信息返回值: {$content}", [$uri]);

        return json_decode($content);
    }

    public function xcxJsCode2Session($code)
    {
        $uri      = "https://api.weixin.qq.com/sns/jscode2session?appid=$this->appId&secret=$this->appSecret&js_code=$code&grant_type=authorization_code";
        $response = $this->client->request('GET', $uri);
        $content  = $response->getBody()->getContents();
        Log::info("获取小程序用户信息返回值: {$content}");

        return json_decode($content);
    }

    /**
     * 刷新 access_token
     * @return mixed
     */
    public function refreshToken()
    {
        $uri    = 'https://api.weixin.qq.com/cgi-bin/token?';
        $params = [
            'grant_type' => 'client_credential',
            'appid'      => $this->appId,
            'secret'     => $this->appSecret,
        ];
        Log::info("刷新微信接口 access_token 参数:", $params);

        $response = $this->client->request('GET', $uri . http_build_query($params));
        $content  = $response->getBody()->getContents();

        Log::info("刷新微信接口 access_token 返回值: {$content}");

        $data = json_decode($content);

        return data_get($data, 'access_token');
    }

    /**
     * 获取access_token
     */
    public function getAccessToken()
    {
        $this->accessToken = Cache::get('WX_ACCESS_TOKEN_' . $this->appId, '');

//        info($this->accessToken);
//        var_dump(empty($this->accessToken));exit;

//        var_dump(empty($this->accessToken || !$is));exit;
        if (empty($this->accessToken) || !$this->accessTokenIsValid()) {
            $this->accessToken = $this->refreshToken();
            Cache::put('WX_ACCESS_TOKEN_' . $this->appId, $this->accessToken, 110);
        }

        return $this->accessToken;
    }

    public function getTicket()
    {
        $ticket = Cache::get('WX_TICKET_' . $this->appId, '');

        if (empty($ticket)) {
            $ticket = $this->refreshTicket();
            Cache::put('WX_TICKET_' . $this->appId, $ticket, 110);
        }
        return $ticket;
    }

    protected function refreshTicket()
    {
        $r = get('https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='.$this->accessToken.'&type=jsapi')->getBody()->getContents();
        info('获取微信ticket返回值', [$r]);
        $j = json_decode($r, 1);
        $ticket = data_get($j, 'ticket', '');
        return $ticket;
    }


    /**
     * 根据openid获取用户信息
     * @param $openId
     * @return mixed
     */
    public function getUserInfo($openId)
    {
        $uri    = "https://api.weixin.qq.com/cgi-bin/user/info?";
        $params = [
            'access_token' => $this->accessToken,
            'openid'       => $openId,
            'lang'         => 'zh_CN',
        ];
        Log::info("获取微信用户信息请求参数:", $params);

        $response = $this->client->request('GET', $uri . http_build_query($params));
        $content  = $response->getBody()->getContents();

        Log::info("获取微信用户信息返回值: {$content}");

        return json_decode($content);
    }

    /**
     * 获取微信服务器IP地址
     * @return string
     */
    public function fetchCallbackIp()
    {
        $uri     = "https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=$this->accessToken";
        $content = $this->client->get($uri)->getBody()->getContents();
        return $content;
    }

    /**
     * 判断当前access_token是否有效
     * @return bool
     */
    public function accessTokenIsValid()
    {
        $res = $this->fetchCallbackIp();
        if (strstr($res, 'ip_list')) {
            return true;
        }
        return false;
    }

    public function snsUserInfo($openId, $accessToken)
    {
        $uri      = "https://api.weixin.qq.com/sns/userinfo?access_token=$accessToken&openid=$openId";
        $response = $this->client->request('GET', $uri);
        $content  = $response->getBody()->getContents();
        info('sns获取用户信息', [$openId, $accessToken, $content]);
        return $content;
    }

    /**  获取小程序访客数量接口
     * @param $type
     * @param $begin_date
     * @param $end_date
     */
    public function getVisitTrend($type, $begin_date, $end_date)
    {
        $params['begin_date'] = date('Ymd', strtotime("-1 day", strtotime($begin_date)));
        $params['end_date']   = date('Ymd', strtotime("-1 day", strtotime($end_date)));
        switch ($type) {
            case 'day':
                $url = 'https://api.weixin.qq.com/datacube/getweanalysisappiddailyvisittrend?access_token=' . $this->accessToken;
                break;
            case 'week':
                $url = 'https://api.weixin.qq.com/datacube/getweanalysisappidweeklyvisittrend?access_token=' . $this->accessToken;
                break;
            case  'month':
                $url = 'https://api.weixin.qq.com/datacube/getweanalysisappidmonthlyvisittrend?access_token=' . $this->accessToken;
                break;
            default:
                throw new \LogicException('请求参数非法');
        }
        $response = postJson($url, $params)->getBody()->getContents();
        info('获取小程序访客数量入参，出参', [$params, $response]);
        //$res = data_get(json_decode($response, true),'list');
        return json_decode($response, true);
    }

    /**  微步信号的模板消息发送
     * @param $open_id
     * @param $param
     * @param $template_id
     */
    public static function messageTemplate($open_id,$param,$template_id='')
    {
        if($template_id=='') $template_id = 'HcrZ7NRxpC7JL4x1ZMkrroebHIrYD8OgJKKv37zbdUc';  //比赛计时提醒的消息模板
        $access_token = Cache::get('WX_ACCESS_TOKEN_'.config('payment.weibu.wechat.app_id'));
        $url='https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='.$access_token;
        $color = '#173177';
        $params['touser'] = $open_id;
        $params['template_id'] = $template_id;
        $params['data']['first'] = [
            'value'=>$param['first'],
            'color'=>$color,
        ];
        $params['data']['keyword1'] = [
            'value'=>$param['keyword1'],
            'color'=>$color,
        ];
        if(isset($param['keyword2'])&&!empty($param['keyword2']))
        {
            $params['data']['keyword2'] = [
                'value'=>$param['keyword2'],
                'color'=>$color,
            ];
        }
        if(isset($param['keyword3'])&&!empty($param['keyword3']))
        {
            $params['data']['keyword3'] = [
                'value'=>$param['keyword3'],
                'color'=>$color,
            ];
        }
        if(isset($param['keyword4'])&&!empty($param['keyword4']))
        {
            $params['data']['keyword4'] = [
                'value'=>$param['keyword4'],
                'color'=>$color,
            ];
        }
        if(isset($param['keyword5'])&&!empty($param['keyword5']))
        {
            $params['data']['keyword5'] = [
                'value'=>$param['keyword5'],
                'color'=>$color,
            ];
        }
        $params['data']['remark'] = [
            'value'=>$param['remark'],
            'color'=>$color,
        ];
        $res = postJson($url, $params)->getBody()->getContents();
        info('微信模板消息', [$res]);
        return $res;
    }

    public function urlscheme($path)
    {
        $parseUrl = parse_url($path);
        $url = "https://api.weixin.qq.com/wxa/generatescheme?access_token=".$this->accessToken;
        $params = [
//            'access_token' => $this->accessToken,
            'jump_wxa' => [
                'path' => data_get($parseUrl, 'path', ''),
                'query' => data_get($parseUrl, 'query', ''),

            ],
            'is_expire' => true,
            'expire_type' => 1,
            'expire_interval' => 179,
        ];
        $r = postJson($url, $params)->getBody()->getContents();
        info('wechat url scheme', [$path, $r]);
//        print_r($r);exit;
        return $r;
    }

    public function createQRCode($path)
    {
        $parseUrl = parse_url($path);
        $url = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=".$this->accessToken;
        $params = [
            'path' => data_get($parseUrl, 'path', ''),
        ];
        $r = postJson($url, $params)->getBody()->getContents();
        info('wechat create qr code', [$path, $r]);
//        print_r($r);exit;
        return $r;
    }

    public function msgSecCheck($content, $openId = '', $scene = '' )
    {
        $curl = "curl -s  -d '{ \"content\":\"$content\" }' 'https://api.weixin.qq.com/wxa/msg_sec_check?access_token=$this->accessToken'";
        $r = `$curl`;
        info('msg sec check', [func_get_args(), $r]);
        $j = json_decode($r, 1);
        if (data_get($j, 'errcode', '') == 87014) {
            throw new \LogicException('存在非法字符，请重新输入', 505);
        }
        return 1;
        return $r;
//        $url = "https://api.weixin.qq.com/wxa/msg_sec_check";
        $url = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=".$this->accessToken;
        $params = [
//            'access_token' => $this->accessToken,
//            'version' => '2',
//            'openid' => $openId,
//            'scene' => $scene,
            'content' => $content,
//            'nickname' => $type,
//            'title' => $type,
//            'signature' => $type,
        ];
        $r = postJson($url, $params)->getBody()->getContents();

//        print_r($r);exit;
        return $r;
    }


    public function getUnlimited($path, $env = 'trial')
    {
        $parseUrl = parse_url($path);
        $url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=".$this->accessToken;
        $params = [
            'page' => data_get($parseUrl, 'path', ''),
            'scene' =>  data_get($parseUrl, 'query', ''),
            'env_version' => $env,
            'auto_color' => false,
            'line_color' => [
                'r' => '250',
                'g' => '251',
                'b' => '252',
            ],
//            'line_color' => '{"r":255,"g":255,"b":255}',
            'is_hyaline' => true,
        ];
        $r = postJson($url, $params)->getBody()->getContents();
        info('get unlimited', [$params, $r]);
        return $r;
    }
}